//-----------------------------------------------------------------------------
//  Copyright (c) 2013 by HangZhou HenqgQiao Design Corporation. All rights reserved.
//
//  Project  : 
//  Module   : over sample the input data with 8-phases 311M clock
//  Parent   : 
//  Children : 
//
//  Description: 
//
//  Parameters:
//  Local Parameters:
//
//  Notes       : 
//
//  Multicycle and False Paths

module SOH4_OBSID(
   input                         SOH4_RESET,
   input                         SOH4_RCLK,

   input[7:0]                    OBSID_IN_RDATA,
   input                         OBSID_IN_RDEN,
   input[1:0]                    OBSID_IN_RFMCNT4,
   input[8:0]                    OBSID_IN_RFMCNT270,
   input[3:0]                    OBSID_IN_RFMCNT9,

   output                        OBSID_OUT_FP,
   output                        OBSID_OUT_DEN,
   output[7:0]                   OBSID_OUT_DATA,

   input                         MPI_CLK,
   input[4:0]                    MPI_OBSID_ADDR,
   input                         MPI_OBSID_WE,
   input[7:0]                    MPI_OBSID_WD,
   output[7:0]                   MPI_OBSID_RD
   );


wire                             OBWR_FP;
wire                             OBWR_DEN;
wire[7:0]                        OBWR_DATA;
reg[6:0]                         OBWR_BCNT81;
reg                              OBWR_SECTOR;
wire                             OBWR_RDSTART;

reg                              OBRD_RL1_FP, OBRD_RL2_FP;
reg                              OBRD_RL1_DEN, OBRD_RL2_DEN;




wire                             DTRM_CLKA, DTRM_CLKB;
wire                             DTRM_WEA;
wire[9:0]                        DTRM_ADDRA, DTRM_ADDRB;
wire[7:0]                        DTRM_DINA, DTRM_DOUTB;


wire                             CFRD_START;
reg[1:0]                         CFRD_FSM;
reg[4:0]                         CFRD_CNT32;

wire                             CFRM_CLKA, CFRM_CLKB;
wire                             CFRM_WEA;
wire[9:0]                        CFRM_ADDRA, CFRM_ADDRB;
wire[7:0]                        CFRM_DINA, CFRM_DOUTA;
wire[7:0]                        CFRM_DOUTB;

reg                              CFRM_RL1_FP, CFRM_RL2_FP;
reg                              CFRM_RL1_CFEN, CFRM_RL2_CFEN;

wire[6:0]                        CFRD_OUT_CF;
wire                             CFRD_OUT_FP;
wire                             CFRD_OUT_CFEN;




// ++++++++++++++++++ the overhead data b ++++++++++++++++++ //

   assign OBWR_FP           = ( OBSID_IN_RFMCNT4[1:0]==4'd0 && OBSID_IN_RFMCNT270[8:0]==9'd0 && OBSID_IN_RFMCNT9[3:0]==4'd0 && OBSID_IN_RDEN==1'b1 );
   assign OBWR_DEN          = ( OBSID_IN_RDEN==1'b1 && OBSID_IN_RFMCNT4[1:0]==4'd0 && OBSID_IN_RFMCNT270[8:0]<9'd9 );
   assign OBWR_DATA[7:0]    = OBSID_IN_RDATA[7:0];

always @( posedge SOH4_RESET or posedge SOH4_RCLK ) begin
   if ( SOH4_RESET==1'b1 )
      OBWR_BCNT81[6:0]                              <= 7'd0;
   else begin
      if ( OBWR_FP==1'b1 && OBWR_DEN==1'b1 )
         OBWR_BCNT81[6:0]                           <= 7'd1;
      else if ( OBWR_DEN==1'b1 ) begin
         if ( OBWR_BCNT81[6:0]== 7'd80 )
            OBWR_BCNT81[6:0]                        <= 7'd0;
         else
            OBWR_BCNT81[6:0]                        <= OBWR_BCNT81[6:0] +7'd1;
      end
   end
end

always @( posedge SOH4_RESET or posedge SOH4_RCLK ) begin
   if ( SOH4_RESET==1'b1 )
      OBWR_SECTOR                                   <= 1'b0;
   else begin
      if ( OBSID_IN_RFMCNT4[1:0]==2'd3 && OBSID_IN_RFMCNT270[8:0]==9'd269 && OBSID_IN_RFMCNT9[3:0]==4'd8 && OBSID_IN_RDEN==1'b1 )
         OBWR_SECTOR                                <= !OBWR_SECTOR;
   end
end
  assign OBWR_RDSTART      = ( OBSID_IN_RFMCNT4[1:0]==2'd3 && OBSID_IN_RFMCNT270[8:0]==9'd269 && OBSID_IN_RFMCNT9[3:0]==4'd8 && OBSID_IN_RDEN==1'b1 );


  assign DTRM_CLKA         = SOH4_RCLK;
  assign DTRM_WEA          = OBWR_DEN;
  assign DTRM_ADDRA[9:0]   = { 2'd0, OBWR_SECTOR, OBWR_BCNT81[6:0] };
  assign DTRM_DINA[7:0]    = OBWR_DATA[7:0];

  assign DTRM_CLKB         = SOH4_RCLK;
  assign DTRM_ADDRB[9:0]   = { 2'd0, !OBWR_SECTOR, CFRD_OUT_CF[6:0] };
SOH4_OBSID_DTRM                   INST_OBSID_DTRM(
   .CLKA                          ( DTRM_CLKA ),
   .WEA                           ( DTRM_WEA ),
   .ADDRA                         ( DTRM_ADDRA[9:0] ),
   .DINA                          ( DTRM_DINA[7:0] ),

   .CLKB                          ( DTRM_CLKB ),
   .ADDRB                         ( DTRM_ADDRB[9:0] ),
   .DOUTB                         ( DTRM_DOUTB[7:0] )
   );


always @( posedge SOH4_RESET or posedge SOH4_RCLK ) begin
   if ( SOH4_RESET==1'b1 ) begin
      OBRD_RL1_FP                                   <= 1'b0;
      OBRD_RL2_FP                                   <= 1'b0;
      OBRD_RL1_DEN                                  <= 1'b0;
      OBRD_RL2_DEN                                  <= 1'b0;
   end
   else begin
      OBRD_RL1_FP                                   <= CFRD_OUT_FP;
      OBRD_RL2_FP                                   <= OBRD_RL1_FP;
      OBRD_RL1_DEN                                  <= CFRD_OUT_CFEN;
      OBRD_RL2_DEN                                  <= OBRD_RL1_DEN;
   end
end
  assign OBSID_OUT_FP           = OBRD_RL2_FP;
  assign OBSID_OUT_DEN          = OBRD_RL2_DEN;
  assign OBSID_OUT_DATA[7:0]    = DTRM_DOUTB[7:0];






// ++++++++++++++++++            MPI configuration  RAM control          ++++++++++++++++++ //

  assign CFRD_START      = OBWR_RDSTART;
always @( posedge SOH4_RESET or posedge SOH4_RCLK ) begin
   if ( SOH4_RESET==1'b1 )
      CFRD_FSM[1:0]                                        <= 2'd0;
   else begin
      case ( CFRD_FSM[1:0] )
      2'd0: begin
         if ( CFRD_START==1'b1 )
            CFRD_FSM[1:0]                                  <= 2'd1;
      end
      2'd1:CFRD_FSM[1:0]                                   <= 2'd2;
      2'd2: begin
         if ( CFRD_CNT32[4:0]==5'd31 )
            CFRD_FSM[1:0]                                  <= 2'd0;
      end
      default: CFRD_FSM[1:0]                               <= 2'd0;
      endcase
   end
end

always @( posedge SOH4_RESET or posedge SOH4_RCLK ) begin
   if ( SOH4_RESET==1'b1 )
      CFRD_CNT32[4:0]                                      <= 5'd0;
   else begin
      if ( CFRD_FSM[1:0]==2'd1 || CFRD_FSM[1:0]==2'd2 )
         CFRD_CNT32[4:0]                                   <= CFRD_CNT32[4:0] +5'd1;
      else
         CFRD_CNT32[4:0]                                   <= 5'd0;
   end
end



  assign  CFRM_CLKA        = MPI_CLK;
  assign  CFRM_WEA         = MPI_OBSID_WE;
  assign  CFRM_DINA[7:0]   = MPI_OBSID_WD[7:0];
  assign  CFRM_ADDRA[9:0]  = {5'd0, MPI_OBSID_ADDR[4:0]};
  assign  MPI_OBSID_RD[7:0]= CFRM_DOUTA[7:0];

  assign  CFRM_CLKB        = SOH4_RCLK;
  assign  CFRM_ADDRB[9:0]  = {5'd0, CFRD_CNT32[4:0] };      // output 1 byte on serial interface every 32-clock cycles, discard the bit4-bit0 in byte map configuration read address

SOH4_OBSID_CFRM                    INST_OBSID_CFRM(
   .CLKA                           ( CFRM_CLKA ),
   .WEA                            ( CFRM_WEA ),
   .ADDRA                          ( CFRM_ADDRA[9:0] ),
   .DINA                           ( CFRM_DINA[7:0] ),
   .DOUTA                          ( CFRM_DOUTA[7:0] ),

   .CLKB                           ( CFRM_CLKB ),
   .ADDRB                          ( CFRM_ADDRB[9:0] ),
   .DOUTB                          ( CFRM_DOUTB[7:0] )
   );


always @( posedge SOH4_RESET or posedge SOH4_RCLK ) begin
   if ( SOH4_RESET==1'b1 ) begin
      CFRM_RL1_FP                                          <= 1'b0;
      CFRM_RL2_FP                                          <= 1'b0;
      CFRM_RL1_CFEN                                        <= 1'b0;
      CFRM_RL2_CFEN                                        <= 1'b0;
   end
   else begin
      CFRM_RL1_FP                                          <= ( CFRD_FSM[1:0]==2'd1 );
      CFRM_RL2_FP                                          <= CFRM_RL1_FP;
      CFRM_RL1_CFEN                                        <= ( CFRD_FSM[1:0]==2'd1 ) || ( CFRD_FSM[1:0]==2'd2 );
      CFRM_RL2_CFEN                                        <= CFRM_RL1_CFEN;
   end
end
   assign CFRD_OUT_CF[6:0]       = CFRM_DOUTB[6:0];
   assign CFRD_OUT_FP            = CFRM_RL2_FP;
   assign CFRD_OUT_CFEN          = CFRM_RL2_CFEN;

endmodule


